#include "Table.h"
#include "Util.h"

vector<string> stackVector; // 当前栈
vector<int> readerVector; // 待读队列
map<int, string> map_i2s = {
        {1,  "int"},
        {2,  "void"},
        {3,  "return"},
        {4,  "const"},
        {5,  "main"},
        {6,  "float"},
        {7,  "if"},
        {8,  "else"},
        {9,  "+"},
        {10, "-"},
        {11, "*"},
        {12, "/"},
        {13, "%"},
        {14, "="},
        {15, ">"},
        {16, "<"},
        {17, "!"},
        {18, "=="},
        {19, "<="},
        {20, ">="},
        {21, "!="},
        {22, "&&"},
        {23, "||"},
        {24, "("},
        {25, ")"},
        {26, "{"},
        {27, "}"},
        {28, ";"},
        {29, ","},
        {30, "Ident"},
        {31, "IntConst"},
        {32, "floatConst"},
        {33, "#"}

};
map<string, int> map_s2i = {
        {"int",        1},
        {"void",       2},
        {"return",     3},
        {"const",      4},
        {"main",       5},
        {"float",      6},
        {"if",         7},
        {"else",       8},
        {"+",          9},
        {"-",          10},
        {"*",          11},
        {"/",          12},
        {"%",          13},
        {"=",          14},
        {">",          15},
        {"<",          16},
        {"!",          17},
        {"==",         18},
        {"<=",         19},
        {">=",         20},
        {"!=",         21},
        {"&&",         22},
        {"||",         23},
        {"(",          24},
        {")",          25},
        {"{",          26},
        {"}",          27},
        {";",          28},
        {",",          29},
        {"Ident",      30},
        {"IntConst",   31},
        {"floatConst", 32},
        {"#",          33}

};

void getTable() {
    initProductions(grammar_path);
    First();
    Follow();
    outputVnVt();
    setPrediction();
}

string initLine(string line) {
    if (line.empty()) {
        return line;
    }
    if (line == ",  <SE,29>") {
        line = "29,,";
        return line;
    }
    size_t strStartIndex_0 = line.find('\t');
    if (strStartIndex_0 != string::npos) {
        line = line.substr(strStartIndex_0);
    }

    size_t strStartIndex_1 = line.find('<');
    size_t strStartIndex_2 = line.find(',');
    size_t strStartIndex_3 = line.find('>');

    if (strStartIndex_1 != string::npos && strStartIndex_2 != string::npos) {
        string token = line.substr(strStartIndex_1 + 1, strStartIndex_2 - strStartIndex_1 - 1);
        if (token == "IDN") {
            line = "30,Ident";
        } else if (token == "INT") {
            line = "31,IntConst";
        } else if (token == "FLOAT") {
            line = "32,floatConst";
        } else if (strStartIndex_3 != string::npos) {
            string key = line.substr(strStartIndex_2 + 1, strStartIndex_3 - strStartIndex_2 - 1);
            int keyNum = stoi(key);
            if (map_i2s.find(keyNum) != map_i2s.end()) {
                line = key + "," + map_i2s[keyNum];
            }
        }
    }

    return line;
}

void readToReader(const string &filePath) {
    ifstream file(filePath); // 打开文件
    if (!file.is_open()) {
        cerr << "Error opening file: " << filePath << endl;
        return;
    }
    string line;
    while (getline(file, line)) { // 读取文件的每一行
        line = initLine(line); // 对行进行预处理
        istringstream iss(line);
        string token;
        if (getline(iss, token, ',')) { // 使用逗号作为分隔符读取行中的第一部分
            try {
                int value = stoi(token); // 将字符串转换为整数
                readerVector.push_back(value); // 添加到reader向量中
            } catch (const exception &e) {
                cerr << "Error converting string to integer: " << e.what() << endl;
            }
        }
    }
    file.close(); // 关闭文件
}

//分析时根据栈顶元素和队头元素确定选用的产生式
int getProductionIndex(int readerTop, int stackTop) {
    if (readerTop < 0 || readerTop >= readerVector.size() || stackTop < 0 || stackTop >= stackVector.size()) {
        cerr << "Error: Index out of bounds." << endl;
        return -1;
    }
    string terminal = map_i2s.at(readerVector[readerTop]);
    string nonTerminal = stackVector[stackTop];
    string key = getMapKey(terminal, nonTerminal);
    auto it = predictionTable.find(key);
    if (it != predictionTable.end()) {
        if (nonTerminal == "elsePart" && terminal == "else") {
            return 43;
        }
        return it->second;
    } else {
        cerr << "Error: No production_map found for the given terminal and non-terminal." << endl;
        return -1;
    }
}


int stackPush(int stackTop, const Production &production) {

    int len = (int) production.right_string.size(); // 获取产生式右侧符号的数量
    stackVector.pop_back();

    if (production.right_string.empty() || production.right_string[0] == "$") {
        // 如果产生式右侧第一个元素是"$"，表示空产生式，不进行压栈
        stackTop--;
        return stackTop;
    } else {
        // 从右到左将产生式的右侧符号压入栈中
        for (int i = len - 1; i >= 0; i--) {
            stackVector.push_back(production.right_string[i]);
        }
        // 返回更新后的栈顶位置，这里假设栈顶位置变化为增加的符号数-1
        return stackTop + len - 1;
    }
}

int doSyntaxAnalysis() {
    string path = lexResultTxt;
    int stackTop = 1;
    int readerTop = 0;
    int index = 1;
    stackVector.push_back(to_string(map_s2i["#"]));
    stackVector.push_back(start);
    ostringstream outputBuffer;
    const string &file_path = path;
    string out;

    try {
        readToReader(file_path);
    } catch (const exception &e) {
        cerr << "Failed to Read LA Result：" << e.what() << endl;
        return 1;
    }

    readerVector.push_back(map_s2i["#"]);

    while (stackTop >= 0) {
        outputBuffer << index << "\t";
        string str = stackVector[stackTop];
        string s;
        int temp = atoi(stackVector[stackTop].c_str());
        if (temp != 0) {
            str = map_i2s.at(temp);
        }
        cout << index << " ";
        cout << str;
        outputBuffer << str;

        cout << "#" << map_i2s[readerVector[0]] << " ";
        outputBuffer << "#" << map_i2s[readerVector[0]] << " ";

        if (str == map_i2s.at(readerVector[readerTop])
            || temp == readerVector[readerTop]) {
            stackVector.erase(stackVector.begin() + stackTop);
            readerVector.erase(readerVector.begin() + readerTop);
            stackTop--;
            cout << "move" << endl;
            outputBuffer << "\t" << "move" << "\n";
        } else {
            int i = getProductionIndex(readerTop, stackTop);
            if (i == -1) {
                cout << "Error" << endl;
                outputBuffer << "Error";
                return 1;
            } else {
                stackTop = stackPush(stackTop, *productionsArray[i]);
                cout << "reduction" << std::endl;
                outputBuffer << "\t" << "reduction" << "\n";
            }
        }
        ++index;
    }

    if (stackTop == -1) {
        cout << "Accept" << endl;
        outputBuffer << "Accept" << endl;
    }

    ofstream outputFile(synResultTxt);
    if (!outputFile) {
        cerr << "Failed to Open Output File" << synResultTxt << endl;
        return 1;
    }

    outputFile << outputBuffer.str();
    outputFile.close();
    return 0;
}

//int main() {
//    getTable();
//    doSyntaxAnalysis();
//    return 0;
//}